package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// 模拟的数据
var secrets = gin.H{
	"weiyigeek": gin.H{"email": "master@weiyigeek.top", "blog": "weiyigeek.top"},
}

func setupRouter() *gin.Engine {
	// Disable Console Color
	gin.DisableConsoleColor()

	// Default返回一个Engine实例，该实例已连接Logger和Recovery中间件。
	r := gin.Default()

	// 示例1. 使用现有的基础请求对象解析查询字符串参数。
	// 示例 URL：/param_get?firstname=Weiyi&lastname=Geek
	r.GET("/param_get", func(c *gin.Context) {
		firstname := c.DefaultQuery("firstname", "Guest")
		lastname := c.Query("lastname") // 注意: c.Request.URL.Query().Get("lastname") 的一种快捷方式
		c.String(http.StatusOK, "Hello %s %s, Welcome To Study Go Gin!", firstname, lastname)
	})

	// 示例2.提交常规类型的数据表单并解析POST请求数据字符串参数。
	// Content-Type: application/x-www-form-urlencoded
	r.POST("/form_post", func(c *gin.Context) {
		name := c.PostForm("name")
		msg := c.DefaultPostForm("message", "empty")
		c.JSON(http.StatusOK, gin.H{"code": 200, "data": gin.H{"name": name, "message": msg}})
	})

	// 示例3.使用QueryMap、PostFormMap 函数映射查询字符串或表单参数
	// Content-Type: application/x-www-form-urlencoded
	r.POST("/form_getpostmap", func(c *gin.Context) {
		post_id := c.QueryMap("id")
		post_info := c.PostFormMap("user")
		c.JSON(http.StatusOK, gin.H{"code": 200, "id": post_id, "post": post_info})
	})

	// 示例4.获取URL路由中的参数
	// 此 handler 将匹配 /router_get/john (但不会匹配 /router_get/ 或者 /router_get)
	r.GET("/router_get/:name", func(c *gin.Context) {
		name := c.Param("name")
		c.String(http.StatusOK, "Hello %s", name)
	})
	// 此 handler 将匹配 /router_get/john/ 和 /router_get/john/send (若如果没有其他路由匹配 /router_get/john，它将重定向到 /router_get/john/)
	r.GET("/router_get/:name/*action", func(c *gin.Context) {
		name := c.Param("name")
		action := c.Param("action")
		message := name + " is " + action
		c.String(http.StatusOK, message)
	})

	// 示例6.c.ShouldBind 函数：针对提交URL参数进行自动选择合适的绑定。
	//GET  /router_get/login?user=weiyigeek&password=123456
	r.GET("/router_get/login", func(c *gin.Context) {
		// 你可以使用显式绑定声明绑定 Query Param：
		// c.ShouldBindWith(&form, binding.Query)
		// 或者简单地使用 ShouldBind 方法自动绑定：
		// POST请求：登录表单的结构体
		type LoginForm struct {
			User     string `form:"user" binding:"required"`
			Password string `form:"password" binding:"required"`
		}
		var login LoginForm
		// 在这种情况下，将自动选择合适的绑定 （值得学习。）
		if c.ShouldBind(&login) == nil {
			if login.User == "user" && login.Password == "password" {
				c.JSON(http.StatusOK, gin.H{"code": 200, "message": "you are logged in"})
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "stmessageatus": "unauthorized"})
			}
		}
	})

	// 示例6.c.ShouldBind 函数：针对提交数据表单进行自动选择合适的绑定。
	// POST /router_get/login
	// ......
	// user=weiyigeek&password=123456
	r.POST("/login", func(c *gin.Context) {
		// 简单地使用 ShouldBind 方法自动绑定：
		// POST请求：登录表单的结构体
		type LoginForm struct {
			User     string `form:"user" binding:"required"`
			Password string `form:"password" binding:"required"`
		}
		var login LoginForm

		// 在这种情况下，将自动选择合适的绑定 （值得学习。）
		if c.ShouldBind(&login) == nil {
			if login.User == "weiyigeek" && login.Password == "123456" {
				c.JSON(http.StatusOK, gin.H{"code": 200, "message": "you are logged in"})
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "stmessageatus": "unauthorized"})
			}
		}
	})

	// 示例7.c.ShouldBind 函数绑定 HTML 复选框表单数据
	// <form action="/" method="POST">
	// 	<p>Check some colors</p>
	// 	<label for="red">Red</label>
	// 	<input type="checkbox" name="colors[]" value="red" id="red">
	// 	<label for="green">Green</label>
	// 	<input type="checkbox" name="colors[]" value="green" id="green">
	// 	<label for="blue">Blue</label>
	// 	<input type="checkbox" name="colors[]" value="blue" id="blue">
	// 	<input type="submit">
	// </form>
	r.POST("/mutil_color", func(c *gin.Context) {
		// 绑定 HTML 复选框
		type myForm struct {
			Colors []string `form:"colors[]"`
		}
		var fakeForm myForm
		// 解析 form 表单
		if c.ShouldBind(&fakeForm) == nil {
			// 输出结果: {"code": 200,"color":["red","green","blue"]}
			c.JSON(http.StatusOK, gin.H{"code": 200, "color": fakeForm.Colors})
		}

	})

	return r
}

func main() {
	r := setupRouter()
	// Listen and Server in 0.0.0.0:8080
	r.Run(":8080")
}
